module.exports = function(sequelize, DataTypes) {
  const withPagination = require('sequelize-cursor-pagination')
  const hexUtil = require('../lib/hex')
  var helper = require('../lib/merge')
  var rating = require('./mixins/RatingMixin')

  var Document = sequelize.define(
    'Document',
    helper.mergeWithArray(
      {
        id: {
          type: DataTypes.BIGINT,
          primaryKey: true,
          autoIncrement: true
        },
        isPublished: {
          type: DataTypes.INTEGER
        },
        uuid: {
          type: 'BINARY(16)',
          defaultValue: function() {
            const uuidv1 = require('uuid/v1')

            const buffer = new Buffer(16)
            uuidv1(null, buffer)

            // Optimize uuid sequence for database index performance
            const result = new Buffer(16)
            buffer.copy(result, 0, 6, 8)
            buffer.copy(result, 2, 4, 6)
            buffer.copy(result, 4, 0, 4)
            buffer.copy(result, 8, 8)

            return buffer
          },
          get() {
            let uuid = this.getDataValue('uuid')
            if (!uuid) return null
            return hexUtil.bytesToHex(uuid)
          }
        },
        name: {
          type: DataTypes.STRING(50),
          allowNull: false,
          validate: {
            notEmpty: true
          }
        },
        type: {
          type: DataTypes.ENUM('question', 'page', 'folder')
        },
        data: {
          type: DataTypes.JSON,
          comment: 'data in json form',
          allowNull: false,
          validate: {
            notEmpty: function(obj) {
              if (Object.keys(obj).length === 0) {
                throw new Error('Data is required!')
              }
            }
          }
        },
        layout: {
          type: DataTypes.JSON,
          comment: 'client document layout in json form'
        },
        meta: {
          type: DataTypes.JSON,
          comment: 'meta data of data, could be answers'
        },
        version: {
          type: DataTypes.INTEGER,
          comment: 'Version sequence number'
        },
        taskCount: {
          type: DataTypes.INTEGER,
          defaultValue: 0,
          comment: 'Number of tasks created with this document'
        },
        refCount: {
          type: DataTypes.INTEGER,
          defaultValue: 0,
          comment:
            'Total document number using this document, cannot delete refCount > 0'
        },
        unreadCount: {
          type: DataTypes.INTEGER,
          defaultValue: 0,
          comment: 'Total unread message number on this document'
        },
        commentedCount: {
          type: DataTypes.INTEGER,
          defaultValue: 0,
          comment: 'Total commented number of this document'
        },
        favoritedCount: {
          type: DataTypes.INTEGER,
          defaultValue: 0,
          comment: 'Total favorited number of this document'
        },
        publishedAt: {
          type: DataTypes.DATE
        },
        endAt: {
          type: DataTypes.DATE,
          comment: '截止时间'
        }
      },
      rating(DataTypes).attributes
    ),
    helper.mergeWithArray(
      {
        tableName: 'documents',
        paranoid: true,
        indexes: [
          {
            name: 'uuid_idx',
            fields: ['uuid']
          },
          {
            name: 'task_count_idx',
            fields: ['taskCount']
          },
          {
            name: 'ref_count_idx',
            fields: ['refCount']
          },
          {
            name: 'published_at_idx',
            fields: ['publishedAt']
          }
        ],
        comments: '文件表'
      },
      rating(DataTypes).options
    )
  )

  Document.associate = function(models) {
    this.belongsTo(models.User, {
      as: 'Owner',
      foreignKey: 'userId',
      constraints: false
    })
    this.hasMany(models.Document, {
      foreignKey: 'documentId'
    }) // This adds documentId to version
    this.belongsTo(models.Document, {
      as: 'Current',
      foreignKey: 'currentVersionId',
      constraints: false
    }) // This adds currentVersionId to document
    this.belongsToMany(models.Tag, {
      as: 'TagDocuments',
      through: 'DocumentTag',
      foreignKey: 'documentId'
    }) // This adds documentId to tags
  }

  const options = {
    primaryKeyField: 'id'
  }

  withPagination(options)(Document)

  return Document
}
